#include "VectorField.h"
#include <fstream>
#include <math.h>
#include <vector>
//#define NANO
#define RAINBOW
//#define NIUBI
//#define SPLASH

VectorField::VectorField(void):deltaT(0.8f),maxMag(-1.0f),minMag(10000000000.0f),colorSize(8)
{
	
}

void VectorField::generateMagnitudeField(float *field)
{
	maxMag=(-1.0f);
	minMag=(10000000000.0f);

	//field=new float[xSize*ySize*zSize];

	for(int x=0;x<xSize;++x)
	for(int y=0;y<ySize;++y)
	for(int z=0;z<zSize;++z)
	{
		FVector v=vectorField[(int)x + (int)y*xSize + (int)z*xSize*ySize];

		float mag=sqrt(v.x*v.x+v.y*v.y+v.z*v.z);

		if(mag>maxMag)
			maxMag=mag;
				
		if(mag<minMag)
			minMag=mag;

		field[(int)x + (int)y*xSize + (int)z*xSize*ySize]=mag;
	}

	//scale

	for(int i=0;i<xSize*ySize*zSize;++i)
	{
		field[i]=(field[i]-minMag)/maxMag;
		//field[i]=0.5f;
	}

}

void VectorField::init()
{
	FILE *fp=fopen("supernova.vec","rb");
	fread(vectorField ,sizeof(struct FVector),xSize*ySize*zSize,fp);
	fclose(fp);


	for(int x=0;x<xSize;++x)
		for(int y=0;y<ySize;++y)
			for(int z=0;z<zSize;++z)
			{
				FVector v=vectorField[(int)x + (int)y*xSize + (int)z*xSize*ySize];

				float mag=sqrt(v.x*v.x+v.y*v.y+v.z*v.z);

				if(mag>maxMag)
					maxMag=mag;
				
				if(mag<minMag)
					minMag=mag;
			}



#ifdef NANO
	colorSize=8;

	colorS=new int[(colorSize+1)*3];

	{

		colorS[0]=228;
		colorS[1]=228;		
		colorS[2]=228;
				
		colorS[3]=129;
		colorS[4]=127;
		colorS[5]=130;
				
		colorS[6]=146;
		colorS[7]=116;
		colorS[8]=211;
				
		colorS[9]=31;
		colorS[10]=166;
		colorS[11]=219;
				
		colorS[12]=147;
		colorS[13]=218;
		colorS[14]=87;
																														
		colorS[15]=239;		
		colorS[16]=210;
		colorS[17]=39;
		
		colorS[18]=249;
		colorS[19]=160;
		colorS[20]=48;

		colorS[21]=248;
		colorS[22]=30;
		colorS[23]=53;

		colorS[24]=247;
		colorS[25]=78;
		colorS[26]=180;

		

	}

	#endif


	#ifdef RAINBOW
	colorSize=5;

	colorS=new int[(colorSize+1)*3];

	{

		colorS[0]=255;
		colorS[1]=17;		
		colorS[2]=17;
				
		colorS[3]=255;
		colorS[4]=186;
		colorS[5]=78;
				
		colorS[6]=254;
		colorS[7]=255;
		colorS[8]=17;
				
		colorS[9]=112;
		colorS[10]=245;
		colorS[11]=84;
				
		colorS[12]=102;
		colorS[13]=87;
		colorS[14]=245;
																														
		colorS[15]=181;		
		colorS[16]=87;
		colorS[17]=245;
		

		

	}

	#endif


	#ifdef SPLASH
	colorSize=5;

	colorS=new int[(colorSize+1)*3];

	{

		colorS[0]=19;
		colorS[1]=65;		
		colorS[2]=93;
				
		colorS[3]=100;
		colorS[4]=155;
		colorS[5]=178;
				
		colorS[6]=192;
		colorS[7]=213;
		colorS[8]=226;
				
		colorS[9]=243;
		colorS[10]=143;
		colorS[11]=246;
				
		colorS[12]=174;
		colorS[13]=174;
		colorS[14]=174;
																														
		colorS[15]=98;		
		colorS[16]=98;
		colorS[17]=98;
		

		

	}

	#endif
	
	#ifdef NIUBI
	colorSize=15;

	colorS=new int[(colorSize+1)*3];

	{

		colorS[0]=255;
		colorS[1]=255;		
		colorS[2]=95;
				
		colorS[3]=204;
		colorS[4]=232;
		colorS[5]=88;
				
		colorS[6]=148;
		colorS[7]=215;
		colorS[8]=82;
				
		colorS[9]=90;
		colorS[10]=203;
		colorS[11]=80;
				
		colorS[12]=81;
		colorS[13]=213;
		colorS[14]=181;
																														
		colorS[15]=82;		
		colorS[16]=178;
		colorS[17]=214;
		

		colorS[18]=80;		
		colorS[19]=148;
		colorS[20]=206;

		colorS[21]=79;		
		colorS[22]=108;
		colorS[23]=203;

		colorS[24]=94;		
		colorS[25]=77;
		colorS[26]=199;

				colorS[27]=148;		
		colorS[28]=76;
		colorS[29]=196;

				colorS[30]=212;		
		colorS[31]=80;
		colorS[32]=197;

						
	
		colorS[33]=232;		
		colorS[34]=89;
		colorS[35]=149;
		
		colorS[36]=255;		
		colorS[37]=97;
		colorS[38]=97;

		colorS[39]=255;		
		colorS[40]=137;
		colorS[41]=97;

		colorS[42]=255;		
		colorS[43]=166;
		colorS[44]=95;

		colorS[45]=255;		
		colorS[46]=187;
		colorS[47]=97;

	}

	#endif



	colorCount=new float[colorSize];

	for(int i=0;i<colorSize;++i)
		colorCount[i]=0;
	
	for(int x=0;x<xSize;++x)
	for(int y=0;y<ySize;++y)
	for(int z=0;z<zSize;++z)
	{
		FVector v=vectorField[(int)x + (int)y*xSize + (int)z*xSize*ySize];

		float mag=sqrt(v.x*v.x+v.y*v.y+v.z*v.z);

		int id=(int)((mag-minMag)/(maxMag-minMag)*colorSize);

		if(id>=colorSize)
			id=colorSize-1;

		colorCount[id]++;
	}

	overall=xSize*ySize*zSize;

	for(int i=0;i<colorSize;++i)
		colorCount[i]=overall/colorCount[i];

		overall=0.0f;

	for(int i=0;i<colorSize;++i)
		overall+=colorCount[i];


}

void VectorField::getColorByDir(float x,float y,float z,int color[])
{
	FVector v=getVector(x,y,z);

	float len=sqrt(v.x*v.x+v.y*v.y+v.z*v.z);

	v.x/=len;
	v.y/=len;
	v.z/=len;


	color[0]=255.0f*v.x;
	color[1]=255.0f*v.y;
	color[2]=255.0f*v.z;
}

void VectorField::getColor(float value,int color[])
{
	float tempValue=value;
	float prevTempValue=0.0f;

	int i=0;
	for( i=0;i<colorSize;++i)
	{
		prevTempValue=tempValue;
		tempValue-=colorCount[i];
		if(tempValue<0)
			break;
	}

	float ratio=prevTempValue/colorCount[i];

	color[0]=colorS[i*3]*(1.0f-ratio)+colorS[(i+1)*3]*ratio;
	color[1]=colorS[i*3+1]*(1.0f-ratio)+colorS[(i+1)*3+1]*ratio;
	color[2]=colorS[i*3+2]*(1.0f-ratio)+colorS[(i+1)*3+2]*ratio;
}

VectorField::~VectorField(void)
{
	delete [] colorCount;
	delete [] colorS;
}

FVector VectorField::getVector(float x,float y,float z)
{

	if(x>(float)(xSize-1) || x<0.0f || y>(float)(ySize-1) || y<0.0f || z<0.0f ||z>(float)(zSize-1))
	{
		FVector i1;
		i1.x=0.0f;
		i1.y=0.0f;
		i1.z=0.0f;
		return i1;
	}

	float xd=x-(int)x;
	float yd=y-(int)y;
	float zd=z-(int)z;

	float azd=1.0f-zd;

	FVector l=vectorField[(int)x + (int)y*xSize + (int)z*xSize*ySize];
	FVector r=vectorField[(int)x + (int)y*xSize + ((int)z+1)*xSize*ySize];

	FVector i1;
	i1.x=l.x*azd+r.x*zd;
	i1.y=l.y*azd+r.y*zd;
	i1.z=l.z*azd+r.z*zd;

	l=vectorField[(int)x + ((int)y+1)*xSize + (int)z*xSize*ySize];
	r=vectorField[(int)x + ((int)y+1)*xSize + ((int)z+1)*xSize*ySize];

	FVector i2;
	i2.x=l.x*azd+r.x*zd;
	i2.y=l.y*azd+r.y*zd;
	i2.z=l.z*azd+r.z*zd;


	l=vectorField[(int)x+1 + (int)y*xSize + (int)z*xSize*ySize];
	r=vectorField[(int)x+1 + (int)y*xSize + ((int)z+1)*xSize*ySize];

	FVector j1;
	j1.x=l.x*azd+r.x*zd;
	j1.y=l.y*azd+r.y*zd;
	j1.z=l.z*azd+r.z*zd;

	l=vectorField[(int)x+1 + ((int)y+1)*xSize + (int)z*xSize*ySize];
	r=vectorField[(int)x+1 + ((int)y+1)*xSize + ((int)z+1)*xSize*ySize];

	FVector j2;
	j2.x=l.x*azd+r.x*zd;
	j2.y=l.y*azd+r.y*zd;
	j2.z=l.z*azd+r.z*zd;


	FVector w1;
	w1.x=i1.x*(1.0f-yd)+i2.x*yd;
	w1.y=i1.y*(1.0f-yd)+i2.y*yd;
	w1.z=i1.z*(1.0f-yd)+i2.z*yd;

	FVector w2;
	w2.x=j1.x*(1.0f-yd)+j2.x*yd;
	w2.y=j1.y*(1.0f-yd)+j2.y*yd;
	w2.z=j1.z*(1.0f-yd)+j2.z*yd;

	FVector result;	
	result.x=w1.x*(1.0f-xd)+w2.x*xd;
	result.y=w1.y*(1.0f-xd)+w2.y*xd;
	result.z=w1.z*(1.0f-xd)+w2.z*xd;

	return result;
}
